package ClientandServer;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

public class Server {
    private static final int PORT = 12345;
    private static final ConcurrentHashMap<Socket, String> clients = new ConcurrentHashMap<>();
    private static final CopyOnWriteArrayList<String> messages = new CopyOnWriteArrayList<>();

    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();

        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("Server started on port " + PORT);

            while (true) {
                Socket clientSocket = serverSocket.accept();
                executor.submit(() -> handleClient(clientSocket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }

    private static void handleClient(Socket socket) {
        try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {

            String username = getUsernameFromClient(in, out);
            if (username == null) {
                return; // Invalid login or registration
            }

            clients.put(socket, username);
            broadcastMessage("User " + username + " has joined the chat.");

            String message;
            while ((message = in.readLine()) != null) {
                if (message.startsWith("/whisper ")) {
                    handleWhisper(message, out);
                } else {
                    broadcastMessage(username + ": " + message);
                }
            }

            clients.remove(socket);
            broadcastMessage("User " + username + " has left the chat.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String getUsernameFromClient(BufferedReader in, PrintWriter out) throws IOException {
        // This is a simplified version of user registration and login.
        // In a real application, you would need to store user credentials securely.
        System.out.println("Waiting for username..."); // For demonstration purposes, this is printed to the console.
        String username = in.readLine();
        if (clients.containsValue(username)) {
            out.println("Username already taken. Please choose another one.");
            return null;
        }
        return username;
    }

    private static void broadcastMessage(String message) {
        synchronized (messages) {
            messages.add(message);
            for (String clientUsername : clients.values()) {
                // Here you would send the message to each client.
                // For simplicity, we just print it to the console.
                System.out.println("To " + clientUsername + ": " + message);
                // In a real application, you would use a map of PrintWriter objects
                // to send the message to each client's socket.
            }
        }
    }

    private static void handleWhisper(String message, PrintWriter out) {
        // Parse the whisper command and send the message to the specified user.
        // For simplicity, this is not implemented here.
        System.out.println("Whisper received: " + message); // For demonstration purposes
    }
}